home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / net / dnet_src.lha / dnet / amiga / doshand / nfs-handler.c < prev   
C/C++ Source or Header  |  1989-12-03  |  26KB  |  1,041 lines

  1.  
  2. /*
  3.  *  NFS-HANDLER.C    V1.11    27-June-89
  4.  *
  5.  *  DNet DOS level NFS handler.
  6.  *
  7.  *  By Matthew Dillon.
  8.  *
  9.  *  This handler converts DOS packets into a form suitable for transmission
  10.  *  over a DNet link to a remote server which will execute the operations.
  11.  */
  12.  
  13. #include "dos.h"
  14. #include <exec/alerts.h>
  15.  
  16. #define BTOC(bp)    ((void *)(((long)bp) << 2))
  17. #define CTOB(cp)    ((BPTR)(((long)cp) >> 2))
  18.  
  19. /*
  20.  *  Since this code might be called several times in a row without being
  21.  *  unloaded, you CANNOT ASSUME GLOBALS HAVE BEEN ZERO'D!!  This also goes
  22.  *  for any global/static assignments that might be changed by running the
  23.  *  code.
  24.  */
  25.  
  26. PROC    *DosProc;   /*    Our Process                    */
  27. DEVNODE *DosNode;   /*    Our DOS node.. created by DOS for us        */
  28. DEVLIST *DevList;   /*    Device List structure for our volume node   */
  29.  
  30. void    *SysBase;   /*    EXEC library base            */
  31. /*
  32. void    *DResBase;
  33. */
  34.  
  35. DOSLIB    *DOSBase;   /*    DOS library base for debug process    */
  36. MLIST    FHBase;     /*    Open Files                */
  37. MLIST    LCBase;     /*    Open Locks                */
  38.  
  39. long    TotalBytes; /*    total bytes of data in filesystem    */
  40.  
  41. void    *CHan;        /*    DNet channel                */
  42. HANDLE    RFRoot;
  43.  
  44. char    TmpBuf[256];
  45.  
  46. #ifdef DEBUG
  47. short DBDisable = 0;    /*  Debug code                    */
  48. #endif
  49.  
  50.  
  51. HANDLE *AllocHandle();
  52.  
  53. /*
  54.  *  Don't call the entry point main().  This way, if you make a mistake
  55.  *  with the compile options you'll get a link error.
  56.  */
  57.  
  58. void __saveds noname ARGS((void));
  59.  
  60. void returnpacket ARGS((PACKET *));
  61. int packetsqueued ARGS((void));
  62. HANDLE *GetHandleForLock ARGS((LOCK *));
  63. void *GetLockForHandle ARGS((HANDLE *));
  64. HANDLE *AllocHandle ARGS((char *, RtOpen *));
  65. void FreeHandle ARGS((HANDLE *));
  66. void *dosalloc ARGS((ulong));
  67. void dosfree ARGS((ulong *));
  68. char *bstos ARGS((ubyte *));
  69. char *skipdevice ARGS((char *));
  70. int DoNetworkOp ARGS((char, void *, int, void *, int, void *, int));
  71.  
  72. void __saveds
  73. noname()
  74. {
  75.     PACKET  *packet;
  76.     short   error;
  77.     MSG     *msg;
  78.     ubyte   notdone;
  79.     void    *tmp;
  80.  
  81. #ifndef LATTICE
  82.     mygeta4();
  83. #endif
  84.  
  85.     /*
  86.      *    Initialize all global variables.  SysBase MUST be initialized before
  87.      *    we can make Exec calls.
  88.      */
  89.  
  90.     TotalBytes = 0;
  91.     SysBase = *(void **)4;
  92.     DOSBase = (void *)OpenLibrary("dos.library",0);
  93.     /*
  94.     DResBase= OpenLibrary("dres.library",0);
  95.     */
  96.     DosProc = (PROC *)FindTask(NULL);
  97.     CHan = 0;
  98.     {
  99.     WaitPort(&DosProc->pr_MsgPort);         /*  Get Startup Packet  */
  100.     msg = GetMsg(&DosProc->pr_MsgPort);
  101.     packet = (PACKET *)msg->mn_Node.ln_Name;
  102.  
  103.     /*
  104.      *  Loading DosNode->dn_Task causes DOS *NOT* to startup a new
  105.      *  instance of the device driver for every reference.    E.G. if
  106.      *  you were writing a CON device you would want this field to
  107.      *  be NULL.
  108.      */
  109.  
  110.     if (DOSBase /*&& DResBase*/) {
  111.         DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
  112.         DEVLIST *dl = dosalloc(sizeof(DEVLIST));
  113.  
  114.         DosNode = BTOC(packet->dp_Arg3);
  115.         DosNode->dn_Task = &DosProc->pr_MsgPort;
  116.  
  117.         /*
  118.          *    Create Volume node and add to the device list.    This will
  119.          *    cause the WORKBENCH to recognize us as a disk.    If we don't
  120.          *    create a Volume node, Wb will not recognize us.  However,
  121.          *    we are a RAM: disk, Volume node or not.
  122.          */
  123.  
  124.         DevList = dl;
  125.         dl->dl_Type = DLT_VOLUME;
  126.         dl->dl_Task = &DosProc->pr_MsgPort;
  127.         dl->dl_DiskType = ID_DOS_DISK;
  128.         dl->dl_Name = (BSTR)DosNode->dn_Name;
  129.         dl->dl_Next = di->di_DevInfo;
  130.         di->di_DevInfo = (long)CTOB(dl);
  131.  
  132.         packet->dp_Res1 = DOS_TRUE;
  133.         packet->dp_Res2 = 0;
  134.     } else {                /*    couldn't open dos.library   */
  135.         packet->dp_Res1 = DOS_FALSE;
  136.         returnpacket(packet);
  137.         return;                /*    exit process            */
  138.     }
  139.     returnpacket(packet);
  140.     }
  141.  
  142.     /*    Initialize  RAM disk    */
  143. #ifdef DEBUG
  144.     dbinit();
  145. #endif
  146.  
  147.     {
  148.     NewList((LIST *)&FHBase);                   /*  more globals    */
  149.     NewList((LIST *)&LCBase);
  150.  
  151.     BZero(&RFRoot, sizeof(RFRoot));
  152.     DateStamp(&RFRoot.Date);
  153.     RFRoot.Type = FILE_DIR;
  154.     RFRoot.Name = "Root";
  155.     }
  156.  
  157.     /*
  158.      *    Here begins the endless loop, waiting for requests over our
  159.      *    message port and executing them.  Since requests are sent over
  160.      *    our message port, this precludes being able to call DOS functions
  161.      *    ourselves (that is why the debugging routines are a separate process)
  162.      */
  163.  
  164. top:
  165.     for (notdone = 1; notdone;) {
  166.     WaitPort(&DosProc->pr_MsgPort);
  167.     while (msg = GetMsg(&DosProc->pr_MsgPort)) {
  168.         packet = (PACKET *)msg->mn_Node.ln_Name;
  169.         packet->dp_Res1 = DOS_TRUE;
  170.         packet->dp_Res2 = 0;
  171.         error = 0;
  172.  
  173.         if (!CHan) {            /*  attempt to open server channel      */
  174.         CHan = DOpen(NULL, PORT_NFS, -80, -80);
  175.         if (!CHan) {        /*  otherwise giveup!                   */
  176.             notdone = 0;
  177.             goto fail;
  178.         }
  179.         }
  180.  
  181. #ifdef DEBUG
  182.         dbprintf("ACTION %ld\n", packet->dp_Type);
  183. #endif
  184.         switch(packet->dp_Type) {
  185.         case ACTION_DIE:        /*    attempt to die?             */
  186.         notdone = 0;        /*    try to die                */
  187.         break;
  188.         case ACTION_OPENRW:     /*    FileHandle,Lock,Name        Bool    */
  189.         case ACTION_OPENOLD:    /*    FileHandle,Lock,Name        Bool    */
  190.         case ACTION_OPENNEW:    /*    FileHandle,Lock,Name        Bool    */
  191.         {
  192.             OpOpen    opkt;
  193.             RtOpen    rpkt;
  194.             short    r;
  195.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg3));
  196.             HANDLE    *handle;
  197.  
  198.             opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg2)->Handle;
  199.             opkt.Modes = packet->dp_Type;
  200.  
  201.             r = DoNetworkOp('O',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  202.             if (r) {
  203.             error = ERROR_OBJECT_IN_USE;
  204.             } else if (rpkt.Handle == -1) {
  205.             error = ERROR_OBJECT_NOT_FOUND;
  206.             } else if (rpkt.Type > 0) {     /* can't open dir */
  207.             OpClose  opkt;
  208.  
  209.             opkt.Handle = rpkt.Handle;
  210.             DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
  211.             error = ERROR_OBJECT_WRONG_TYPE;
  212.             } else {
  213.             if (name[0] == 0)
  214.                 name = GetHandleForLock((LOCK *)packet->dp_Arg2)->Name;
  215.             handle = AllocHandle(name, &rpkt);
  216.             ((FH *)BTOC(packet->dp_Arg1))->fh_Arg1 = (long)handle;
  217.             }
  218.         }
  219.         break;
  220.         case ACTION_READ:        /*     FHArg1,CPTRBuffer,Length   ActLength  */
  221.         {
  222.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  223.             OpRead    opkt;
  224.             RtRead    rpkt;
  225.             short    err;
  226.  
  227.             opkt.Handle = handle->Handle;
  228.             opkt.Bytes        = packet->dp_Arg3;
  229.  
  230.             err = DoNetworkOp('R',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  231.             if (err)
  232.             rpkt.Bytes = -1;
  233.             if (rpkt.Bytes > 0 && rpkt.Bytes <= opkt.Bytes)
  234.             DRead(CHan, (void *)packet->dp_Arg2, rpkt.Bytes);
  235.             packet->dp_Res1 = rpkt.Bytes;
  236.         }
  237.         break;
  238.         case ACTION_WRITE:        /*     FHArg1,CPTRBuffer,Length   ActLength  */
  239.         {
  240.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  241.             OpWrite    opkt;
  242.             RtWrite    rpkt;
  243.             short    err;
  244.  
  245.             opkt.Handle = handle->Handle;
  246.             opkt.Bytes        = packet->dp_Arg3;
  247.  
  248.             err = DoNetworkOp('W',&opkt,sizeof(opkt),(void *)packet->dp_Arg2,packet->dp_Arg3,&rpkt,sizeof(rpkt));
  249.  
  250.             if (err)
  251.             rpkt.Bytes = -1;
  252.             packet->dp_Res1 = rpkt.Bytes;
  253.         }
  254.         break;
  255.         case ACTION_CLOSE:        /*     FHArg1             Bool:TRUE  */
  256.         {
  257.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  258.             OpClose    opkt;
  259.  
  260.             if (packet->dp_Arg1 == NULL || handle->Magic != MAGIC) {
  261.             Alert(AT_Recovery|0, (char *)0x12345555);
  262.             } else {
  263.             opkt.Handle = handle->Handle;
  264.  
  265.             DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
  266.             FreeHandle(handle);
  267.             }
  268.         }
  269.         if (!GetHead(&FHBase))
  270.             notdone = 0;
  271.         break;
  272.         case ACTION_SEEK:        /*     FHArg1,Position,Mode        OldPosition*/
  273.         {
  274.             HANDLE  *handle = (HANDLE *)packet->dp_Arg1;
  275.             OpSeek  opkt;
  276.             RtSeek  rpkt;
  277.             short   err;
  278.  
  279.             opkt.Handle = handle->Handle;
  280.             opkt.Offset = packet->dp_Arg2;
  281.             opkt.How    = packet->dp_Arg3 + 1;
  282.  
  283.             err = DoNetworkOp('S',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  284.             if (err)
  285.             rpkt.NewOffset = -1;
  286.             if (rpkt.NewOffset < 0)
  287.             error = ERROR_SEEK_ERROR;
  288.             else
  289.             packet->dp_Res1 = rpkt.OldOffset;
  290.         }
  291.         break;
  292.         case ACTION_EXAMINE_NEXT: /*   Lock,Fib              Bool     */
  293.         {
  294.             HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  295.             FIB *fib = BTOC(packet->dp_Arg2);
  296.             OpNextDir opkt;
  297.             RtNextDir rpkt;
  298.             short err;
  299.  
  300. #ifdef DEBUG
  301.             dbprintf("FIB = %08lx\n", fib);
  302. #endif
  303.             if (handle->Type < 0) {
  304.             error = ERROR_OBJECT_WRONG_TYPE;
  305.             break;
  306.             }
  307.  
  308.             opkt.Handle = handle->Handle;
  309.             opkt.Index    = fib->fib_DiskKey;
  310.             err = DoNetworkOp('N',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  311.             if (err || rpkt.Handle == -1) {
  312.             error = ERROR_NO_MORE_ENTRIES;
  313.             } else {    /* not a real file handle, just info & name */
  314.             unsigned char fn;
  315.  
  316.             if (DRead(CHan, &fn, 1) != 1)
  317.                 TmpBuf[fn = 0] = 0;
  318.             if (DRead(CHan, TmpBuf, fn) != fn)
  319.                 TmpBuf[fn = 0] = 0;
  320.             ++fib->fib_DiskKey;    /*  next key */
  321.             fib->fib_DirEntryType = rpkt.Type;
  322.             fib->fib_Protection = rpkt.Prot;
  323.             fib->fib_EntryType = NULL;
  324.             fib->fib_Size = rpkt.Size;
  325.             fib->fib_NumBlocks = rpkt.Size >> 9;
  326.             if (strlen(TmpBuf) >= sizeof(fib->fib_FileName) - 2) {
  327.                 fib->fib_FileName[0] = 1;
  328.                 fib->fib_FileName[1] = '?';
  329.                 fib->fib_FileName[2] = 0;
  330.             } else {
  331.                 strcpy(fib->fib_FileName+1, TmpBuf);
  332.                 fib->fib_FileName[0] = strlen(TmpBuf);
  333.             }
  334.             fib->fib_Comment[0] = 0;
  335.             fib->fib_Comment[1] = 0;
  336.             fib->fib_Date = rpkt.Date;
  337.             }
  338.         }
  339.         break;
  340.         case ACTION_EXAMINE_OBJECT: /*   Lock,Fib            Bool       */
  341.         {
  342.             HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  343.             FIB *fib = BTOC(packet->dp_Arg2);
  344.  
  345. #ifdef DEBUG
  346.             dbprintf("FIB = %08lx\n", fib);
  347. #endif
  348.             fib->fib_DiskKey = 0;
  349.             fib->fib_DirEntryType = handle->Type;
  350.             /*
  351.              *    fib->fib_FileName bcpl type string
  352.              */
  353.             fib->fib_Protection = handle->Prot;
  354.             fib->fib_EntryType = NULL;
  355.             fib->fib_Size = handle->Size;
  356.             fib->fib_NumBlocks = handle->Size >> 9;
  357.  
  358.             if (strlen(handle->Name) >= sizeof(fib->fib_FileName) - 2) {
  359.             fib->fib_FileName[0] = 1;
  360.             fib->fib_FileName[1] = '?';
  361.             fib->fib_FileName[2] = 0;
  362.             } else {
  363.             strcpy(fib->fib_FileName+1, handle->Name);
  364.             fib->fib_FileName[0] = strlen(handle->Name);
  365.             }
  366.             fib->fib_Comment[0] = 0;
  367.             fib->fib_Comment[1] = 0;
  368.             fib->fib_Date = handle->Date;
  369.         }
  370.         break;
  371.         case ACTION_INFO:        /*    Lock, InfoData      Bool:TRUE    */
  372.         tmp = BTOC(packet->dp_Arg2);
  373.         error = -1;
  374.         /*  fall through    */
  375.         case ACTION_DISK_INFO:  /*    InfoData      Bool:TRUE    */
  376.         {
  377.             INFODATA *id;
  378.  
  379.             /*
  380.              *    Note:    id_NumBlocks is never 0, but only to get
  381.              *    around a bug I found in my shell (where I divide
  382.              *    by id_NumBlocks).  Other programs probably break
  383.              *    as well.
  384.              */
  385.  
  386.             (error) ? (id = tmp) : (id = BTOC(packet->dp_Arg1));
  387.             error = 0;
  388.             BZero(id, sizeof(*id));
  389.             id->id_DiskState = ID_VALIDATED;
  390.             id->id_NumBlocks     = (TotalBytes >> 9) + 1;
  391.             id->id_NumBlocksUsed = (TotalBytes >> 9) + 1;
  392.             id->id_BytesPerBlock = 512;
  393.             id->id_DiskType = ID_DOS_DISK;
  394.             id->id_VolumeNode = (long)CTOB(DosNode);
  395.             id->id_InUse = (long)GetHead(&LCBase);
  396.         }
  397.         break;
  398.         case ACTION_PARENT:     /*     Lock                ParentLock */
  399.         {
  400.             HANDLE *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  401.             OpParent    opkt;
  402.             RtParent    rpkt;
  403.             short    err;
  404.  
  405.             opkt.Handle = handle->Handle;
  406.  
  407.             err = DoNetworkOp('P',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  408.             if (err)
  409.             rpkt.Handle = NULL;
  410.             if (rpkt.Handle == -1) {
  411.             error = ERROR_OBJECT_NOT_FOUND;
  412.             } else {    /*  create a file handle and return a lock */
  413.             HANDLE *newhandle;
  414.             unsigned char fn;
  415.  
  416.             if (DRead(CHan, &fn, 1) != 1)
  417.                 TmpBuf[fn = 0] = 0;
  418.             if (DRead(CHan, TmpBuf, fn) != fn)
  419.                 TmpBuf[fn = 0] = 0;
  420.             newhandle = AllocHandle(TmpBuf, &rpkt);
  421.             packet->dp_Res1 = (long)GetLockForHandle(newhandle);
  422.             }
  423.         }
  424.         break;
  425.         case ACTION_DELETE_OBJECT: /*Lock,Name            Bool       */
  426.         {
  427.             OpDelete    opkt;
  428.             RtDelete    rpkt;
  429.             short    err;
  430.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
  431.  
  432.             opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
  433.  
  434.             err = DoNetworkOp('D',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  435.             if (err || rpkt.Error)
  436.             error = ERROR_OBJECT_NOT_FOUND;
  437.         }
  438.         break;
  439.         case ACTION_CREATE_DIR: /*     Lock,Name            Lock       */
  440.         {
  441.             OpCreateDir opkt;
  442.             RtCreateDir rpkt;
  443.             short    err;
  444.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
  445.  
  446.             opkt.DirHandle = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
  447.  
  448.             err = DoNetworkOp('M',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  449.             if (err)
  450.             rpkt.Handle = NULL;
  451.             if (rpkt.Handle == -1) {
  452.             error = ERROR_OBJECT_EXISTS;
  453.             } else {    /*  create a file handle and return a lock */
  454.             HANDLE *newhandle = AllocHandle(name, &rpkt);
  455.  
  456.             packet->dp_Res1 = (long)GetLockForHandle(newhandle);
  457.             }
  458.         }
  459.         break;
  460.         case ACTION_LOCATE_OBJECT:    /*   Lock,Name,Mode        Lock       */
  461.         {
  462.             OpOpen    opkt;
  463.             RtOpen    rpkt;
  464.             short    err;
  465.             char    *name = skipdevice(bstos((ubyte *)packet->dp_Arg2));
  466.             HANDLE    *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  467.  
  468.             opkt.DirHandle = handle->Handle;
  469.             opkt.Modes = 1005;
  470.  
  471.             err = DoNetworkOp('O',&opkt,sizeof(opkt),name,strlen(name)+1,&rpkt,sizeof(rpkt));
  472.             if (err) {
  473.             error = ERROR_OBJECT_IN_USE;
  474.             } else if (rpkt.Handle == -1) {
  475.             error = ERROR_OBJECT_NOT_FOUND;
  476.             } else {
  477.             HANDLE *newhandle;
  478.             if (name[0] == 0)
  479.                 name = handle->Name;
  480.  
  481.             newhandle = AllocHandle(name, &rpkt);
  482.             packet->dp_Res1 = (long)GetLockForHandle(newhandle);
  483.             }
  484.         }
  485.         break;
  486.         case ACTION_COPY_DIR:   /*     Lock,                Lock       */
  487.         {
  488.             OpDup    opkt;
  489.             RtDup    rpkt;
  490.             short    err;
  491.             HANDLE    *oldhandle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  492.  
  493.             opkt.Handle = oldhandle->Handle;
  494.  
  495.             err = DoNetworkOp('d',&opkt,sizeof(opkt),NULL,0,&rpkt,sizeof(rpkt));
  496.             if (err) {
  497.             error = ERROR_OBJECT_IN_USE;
  498.             } else if (rpkt.Handle == -1) {
  499.             error = ERROR_OBJECT_NOT_FOUND;
  500.             } else {
  501.             HANDLE *handle = AllocHandle(oldhandle->Name, &rpkt);
  502.  
  503.             packet->dp_Res1 = (long)GetLockForHandle(handle);
  504.             }
  505.         }
  506.         break;
  507.         case ACTION_FREE_LOCK:  /*     Lock,                Bool       */
  508.         {
  509.             HANDLE  *handle = GetHandleForLock((LOCK *)packet->dp_Arg1);
  510.             OpClose    opkt;
  511.  
  512.             opkt.Handle = handle->Handle;
  513.  
  514.             DoNetworkOp('C',&opkt,sizeof(opkt),NULL,0,NULL,0);
  515.             FreeHandle(handle);
  516.         }
  517.         break;
  518.         case ACTION_SET_PROTECT:/*     -,Lock,Name,Mask       Bool       */
  519.         error = ERROR_ACTION_NOT_KNOWN;
  520.         break;
  521.         case ACTION_SET_COMMENT:/*     -,Lock,Name,Comment       Bool       */
  522.         error = ERROR_ACTION_NOT_KNOWN;
  523.         break;
  524.         case ACTION_RENAME_OBJECT:/* SLock,SName,DLock,DName    Bool       */
  525.         {
  526.             OpRename    opkt;
  527.             RtRename    rpkt;
  528.             short    err;
  529.             char    *name1= skipdevice(bstos((ubyte *)packet->dp_Arg2));
  530.             char    *name2= skipdevice(bstos((ubyte *)packet->dp_Arg4));
  531.             short    len1 = strlen(name1);
  532.             short    len2 = strlen(name2);
  533.             char    *name = AllocMem(len1+len2+2, MEMF_PUBLIC);
  534.  
  535.             opkt.DirHandle1 = GetHandleForLock((LOCK *)packet->dp_Arg1)->Handle;
  536.             opkt.DirHandle2 = GetHandleForLock((LOCK *)packet->dp_Arg3)->Handle;
  537.             strcpy(name, name1);
  538.             strcpy(name+len1+1,name2);
  539.  
  540.             err = DoNetworkOp('r',&opkt,sizeof(opkt),name,len1+len2+2,&rpkt,sizeof(rpkt));
  541.             FreeMem(name, len1+len2+2);
  542.             if (err) {
  543.             error = ERROR_OBJECT_IN_USE;
  544.             } else if (rpkt.Error) {
  545.             error = ERROR_OBJECT_NOT_FOUND;
  546.             }
  547.         }
  548.         break;
  549.         /*
  550.          *    A few other packet types which we do not support
  551.          */
  552.         case ACTION_INHIBIT:    /*     Bool                Bool       */
  553.         /*  Return success for the hell of it    */
  554.         break;
  555.         case ACTION_RENAME_DISK:/*     BSTR:NewName            Bool       */
  556.         case ACTION_MORECACHE:  /*     #BufsToAdd            Bool       */
  557.         case ACTION_WAIT_CHAR:  /*     Timeout, ticks         Bool       */
  558.         case ACTION_FLUSH:        /*     writeout bufs, disk motor off           */
  559.         case ACTION_RAWMODE:    /*     Bool(-1:RAW 0:CON)         OldState   */
  560.         default:
  561. fail:
  562.         error = ERROR_ACTION_NOT_KNOWN;
  563.         break;
  564.         }
  565.         if (packet) {
  566.         if (error) {
  567.             packet->dp_Res1 = DOS_FALSE;
  568.             packet->dp_Res2 = error;
  569.         }
  570.         returnpacket(packet);
  571.         }
  572.     }
  573.     }
  574.     Delay(50);      /*  I wanna even see the debug message! */
  575.     Forbid();
  576.     if (packetsqueued() || GetHead(&FHBase)) {
  577.     Permit();
  578.     goto top;        /*  sorry... can't exit     */
  579.     }
  580.  
  581.     /*
  582.      *    Causes a new process to be created on next reference
  583.      */
  584.  
  585.     DosNode->dn_Task = FALSE;
  586.  
  587.     /*
  588.      *    Remove Volume entry.  Since DOS uses singly linked lists, we
  589.      *    must (ugg) search it manually to find the link before our
  590.      *    Volume entry.
  591.      */
  592.  
  593.     {
  594.     DOSINFO *di = BTOC(((ROOTNODE *)DOSBase->dl_Root)->rn_Info);
  595.     DEVLIST *dl;
  596.     void *dlp;
  597.  
  598.     dlp = &di->di_DevInfo;
  599.     for (dl = BTOC(di->di_DevInfo); dl && dl != DevList; dl = BTOC(dl->dl_Next))
  600.         dlp = &dl->dl_Next;
  601.     if (dl == DevList) {
  602.         *(BPTR *)dlp = dl->dl_Next;
  603.         dosfree((ulong *)dl);
  604.     } else {
  605.         ;
  606.     }
  607.     }
  608.  
  609.     /*
  610.      *    closedown, fall of the end of the world
  611.      *
  612.      *    (which is how you kill yourself if a PROCESS.  A TASK would have
  613.      *    had to RemTask(NULL) itself).
  614.      */
  615.  
  616.     if (CHan)
  617.     DClose(CHan);
  618.     CHan = 0;
  619. #ifdef DEBUG
  620.     dbuninit();
  621. #endif
  622.     CloseLibrary((LIB *)DOSBase);
  623.     /*
  624.     CloseLibrary(DResBase);
  625.     */
  626. }
  627.  
  628.  
  629. /*
  630.  *  PACKET ROUTINES.    Dos Packets are in a rather strange format as you
  631.  *  can see by this and how the PACKET structure is extracted in the
  632.  *  GetMsg() of the main routine.
  633.  */
  634.  
  635. void
  636. returnpacket(packet)
  637. PACKET *packet;
  638. {
  639.     struct Message *mess;
  640.     struct MsgPort *replyport;
  641.  
  642.     replyport             = packet->dp_Port;
  643.     mess             = packet->dp_Link;
  644.     packet->dp_Port         = &DosProc->pr_MsgPort;
  645.     mess->mn_Node.ln_Name    = (char *)packet;
  646.     mess->mn_Node.ln_Succ    = NULL;
  647.     mess->mn_Node.ln_Pred    = NULL;
  648.     PutMsg(replyport, mess);
  649. }
  650.  
  651. /*
  652.  *  Are there any packets queued to our device?
  653.  */
  654.  
  655. int
  656. packetsqueued()
  657. {
  658.     return ((void *)DosProc->pr_MsgPort.mp_MsgList.lh_Head !=
  659.         (void *)&DosProc->pr_MsgPort.mp_MsgList.lh_Tail);
  660. }
  661.  
  662. /*
  663.  *  Handle structure, locks, and manipulation.
  664.  */
  665.  
  666. HANDLE *
  667. GetHandleForLock(block)
  668. LOCK *block;
  669. {
  670.     LOCK *lock = BTOC(block);
  671.     HANDLE *handle;
  672.  
  673. #ifdef DEBUG
  674.     dbprintf("GetHandleForLock: %08lx ", lock);
  675. #endif
  676.     if (lock) {
  677.     handle = (HANDLE *)lock->fl_Key;
  678. #ifdef DEBUG
  679.     dbprintf("Handle=%08lx (h=$%08lx)\n", handle, handle->Handle);
  680. #endif
  681.     if (handle->Magic == MAGIC)
  682.         return(handle);
  683.     Alert(AT_Recovery|1, (char *)handle);
  684.     }
  685. #ifdef DEBUG
  686.     dbprintf("\n");
  687. #endif
  688.     /*Alert(AT_Recovery|2, (char *)-2);*/
  689.     return(&RFRoot);
  690. }
  691.  
  692. void *
  693. GetLockForHandle(handle)
  694. HANDLE *handle;
  695. {
  696.     LOCK *lock = handle->Lock;
  697.     LOCKLINK *ln;
  698.  
  699. #ifdef DEBUG
  700.     dbprintf("GetLockForHandle: %08lx ", handle);
  701. #endif
  702.     if (!lock) {
  703.     lock = dosalloc(sizeof(LOCK));
  704. #ifdef DEBUG
  705.     dbprintf("(allocate) %08lx\n", lock);
  706. #endif
  707.     ln = AllocMem(sizeof(LOCKLINK), MEMF_PUBLIC|MEMF_CLEAR);
  708.     AddHead((LIST *)&LCBase,(NODE *)ln);
  709.     ln->Lock = lock;
  710.     lock->fl_Link = (long)ln;
  711.     lock->fl_Key = (long)handle;
  712.     lock->fl_Access = ACCESS_READ;
  713.     lock->fl_Task= &DosProc->pr_MsgPort;
  714.     lock->fl_Volume = (BPTR)CTOB(DosNode);
  715.  
  716.     handle->Lock = lock;
  717.     }
  718. #ifdef DEBUG
  719.     dbprintf("Lock=%08lx\n", lock);
  720. #endif
  721.     return((void *)CTOB(lock));
  722. }
  723.  
  724. HANDLE *
  725. AllocHandle(name, rpkt)
  726. char *name;
  727. RtOpen *rpkt;
  728. {
  729.     HANDLE *handle;
  730.     char *ptr;
  731.  
  732.     for (ptr = name + strlen(name) - 1; ptr >= name && *ptr != '/'; --ptr);
  733.     ++ptr;
  734.  
  735.     handle = AllocMem(sizeof(HANDLE), MEMF_PUBLIC|MEMF_CLEAR);
  736.     handle->Magic = MAGIC;
  737.     handle->Handle= rpkt->Handle;
  738.     handle->Type = rpkt->Type;
  739.     handle->Prot = rpkt->Prot;
  740.     handle->Size = rpkt->Size;
  741.     handle->Name = AllocMem(strlen(ptr)+1, MEMF_PUBLIC);
  742.     handle->Date = rpkt->Date;
  743.     strcpy(handle->Name, ptr);
  744.     AddHead((LIST *)&FHBase, (NODE *)handle);
  745.  
  746. #ifdef DEBUG
  747.     dbprintf("AllocHandle: %08lx '%s' h=$%08lx\n", handle, ptr, handle->Handle);
  748. #endif
  749.     return(handle);
  750. }
  751.  
  752. void
  753. FreeHandle(handle)
  754. HANDLE *handle;
  755. {
  756. #ifdef DEBUG
  757.     dbprintf("FreeHandle: %08lx %08lx\n", handle, handle->Lock);
  758. #endif
  759.     if (handle->Lock) {
  760.     LOCK *lock = handle->Lock;
  761.     Remove((NODE *)lock->fl_Link);
  762.     FreeMem((void *)lock->fl_Link, sizeof(LOCKLINK));
  763.     dosfree((ulong *)lock);
  764.     }
  765.     Remove((NODE *)handle);
  766.     handle->Magic = 0;
  767.     FreeMem(handle->Name, strlen(handle->Name)+1);
  768.     FreeMem(handle, sizeof(HANDLE));
  769. }
  770.  
  771. /*
  772.  *  DOS MEMORY ROUTINES
  773.  *
  774.  *  DOS makes certain assumptions about LOCKS.    A lock must minimally be
  775.  *  a FileLock structure, with additional private information after the
  776.  *  FileLock structure.  The longword before the beginning of the structure
  777.  *  must contain the length of structure + 4.
  778.  *
  779.  *  NOTE!!!!! The workbench does not follow the rules and assumes it can
  780.  *  copy lock structures.  This means that if you want to be workbench
  781.  *  compatible, your lock structures must be EXACTLY sizeof(struct FileLock).
  782.  */
  783.  
  784. void *
  785. dosalloc(bytes)
  786. ulong bytes;
  787. {
  788.     ulong *ptr;
  789.  
  790.     bytes += 4;
  791.     ptr = AllocMem(bytes, MEMF_PUBLIC|MEMF_CLEAR);
  792.     *ptr = bytes;
  793.     return(ptr+1);
  794. }
  795.  
  796. void
  797. dosfree(ptr)
  798. ulong *ptr;
  799. {
  800.     --ptr;
  801.     FreeMem(ptr, *ptr);
  802. }
  803.  
  804. /*
  805.  *  Convert a BSTR into a normal string.. copying the string into buf.
  806.  *  I use normal strings for internal storage, and convert back and forth
  807.  *  when required.
  808.  */
  809.  
  810. char *
  811. bstos(bstr)
  812. ubyte *bstr;
  813. {
  814.     static char buf[512];
  815.     static char *ptr = buf;
  816.  
  817.     if (ptr == buf)     /*  switch which buffer to use */
  818.     ptr = buf + 256;
  819.     else
  820.     ptr = buf;
  821.  
  822.     bstr = BTOC(bstr);
  823.     BMov(bstr+1,ptr,*bstr);
  824.     ptr[*bstr] = 0;
  825.     return(ptr);
  826. }
  827.  
  828. char *
  829. skipdevice(str)
  830. char *str;
  831. {
  832.     char *base = str;
  833.  
  834.     while (*str && *str != ':')
  835.     ++str;
  836.     if (*str == 0)
  837.     str = base;
  838.     else
  839.     ++str;
  840.     return(str);
  841. }
  842.  
  843. /*
  844.  *  data = DoNetworkOp(&cmd, &len, data)
  845.  */
  846.  
  847. int
  848. DoNetworkOp(cmd, s, _slen, d, dlen, r, rlen)
  849. char cmd;
  850. int _slen;
  851. void *s;
  852. void *d;
  853. void *r;
  854. {
  855.     ubyte slen = _slen;
  856.     if (CHan) {
  857.     if (DWrite(CHan, &cmd, 1) < 0)
  858.         goto fail;
  859.     if (DWrite(CHan, &slen, 1) < 0)
  860.         goto fail;
  861.     if (DWrite(CHan, &dlen, 4) < 0)
  862.         goto fail;
  863.     if (DWrite(CHan, s, slen) < 0)
  864.         goto fail;
  865.  
  866.     if (dlen) {
  867.         if (DWrite(CHan, d, dlen) < 0)
  868.         goto fail;
  869.     }
  870.     if (r) {
  871.         if (DRead(CHan, r, rlen) != rlen)
  872.         goto fail;
  873.     }
  874.     return(0);
  875.     }
  876. fail:
  877.     if (CHan) {
  878.     DClose(CHan);
  879.     CHan = 0;
  880.     }
  881.     return(1);
  882. }
  883.  
  884. #ifndef LATTICE
  885.  
  886. #asm
  887.  
  888. _mygeta4:
  889.     far    data
  890.     lea    __H1_org+32766,a4
  891.     rts
  892.  
  893.     public    __H0_org
  894.  
  895.     dseg
  896.  
  897.     public    __H1_org
  898.  
  899.     cseg
  900. #endasm
  901.  
  902. #endif
  903.  
  904.  
  905. #ifdef DEBUG        /*    note, doesn't work w/ Lattice   */
  906.  
  907. /*
  908.  *                DEBUG CODE
  909.  */
  910.  
  911.  
  912.             /*    DEBUGGING            */
  913. PORT *Dbport;        /*    owned by the debug process    */
  914. PORT *Dback;        /*    owned by the DOS device driver    */
  915. MSG DummyMsg;        /*    Dummy message that debug proc can use    */
  916.  
  917. /*
  918.  *  DEBUGGING CODE.    You cannot make DOS library calls that access other
  919.  *  devices from within a DOS device driver because they use the same
  920.  *  message port as the driver.  If you need to make such calls you must
  921.  *  create a port and construct the DOS messages yourself.  I do not
  922.  *  do this.  To get debugging info out another PROCESS is created to which
  923.  *  debugging messages can be sent.
  924.  *
  925.  *  You want the priority of the debug process to be larger than the
  926.  *  priority of your DOS handler.  This is so if your DOS handler crashes
  927.  *  you have a better idea of where it died from the debugging messages
  928.  *  (remember that the two processes are asyncronous from each other).
  929.  */
  930.  
  931. extern void debugproc();
  932.  
  933. dbinit()
  934. {
  935.     TASK *task = FindTask(NULL);
  936.  
  937.     Dback = CreatePort(NULL,NULL);
  938.     CreateProc("DEV_DB", task->tc_Node.ln_Pri+1, CTOB(debugproc), 4096);
  939.     WaitPort(Dback);                                /* handshake startup    */
  940.     GetMsg(Dback);                                  /* remove dummy msg     */
  941.     dbprintf("Debugger running V1.10, 2 November 1987\n");
  942.     dbprintf("Works with WORKBENCH!\n");
  943. }
  944.  
  945. dbuninit()
  946. {
  947.     MSG killmsg;
  948.  
  949.     if (Dbport) {
  950.     killmsg.mn_Length = 0;        /*    0 means die        */
  951.     PutMsg(Dbport,&killmsg);
  952.     WaitPort(Dback);            /*  He's dead jim!      */
  953.     GetMsg(Dback);
  954.     DeletePort(Dback);
  955.  
  956.     /*
  957.      *  Since the debug process is running at a greater priority, I
  958.      *  am pretty sure that it is guarenteed to be completely removed
  959.      *  before this task gets control again.  Still, it doesn't hurt...
  960.      */
  961.  
  962.     Delay(50);                  /*  ensure he's dead    */
  963.     }
  964. }
  965.  
  966. dbprintf(a,b,c,d,e,f,g,h,i,j)
  967. {
  968.     char buf[256];
  969.     MSG *msg;
  970.  
  971.     if (Dbport && !DBDisable) {
  972.     sprintf(buf,a,b,c,d,e,f,g,h,i,j);
  973.     msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
  974.     msg->mn_Length = strlen(buf)+1;     /*  Length NEVER 0  */
  975.     strcpy(msg+1,buf);
  976.     PutMsg(Dbport,msg);
  977.     }
  978. }
  979.  
  980. /*
  981.  *  BTW, the DOS library used by debugmain() was actually openned by
  982.  *  the device driver.    Note: DummyMsg cannot be on debugmain()'s stack
  983.  *  since debugmain() goes away on the final handshake.
  984.  */
  985.  
  986. void
  987. debugmain()
  988. {
  989.     MSG *msg;
  990.     short len;
  991.     void *fh;
  992.  
  993.     mygeta4();
  994.     Dbport = CreatePort(NULL,NULL);
  995.     fh = Open("con:0/0/640/100/debugwindow", 1006);
  996.     PutMsg(Dback, &DummyMsg);
  997.     for (;;) {
  998.     WaitPort(Dbport);
  999.     msg = GetMsg(Dbport);
  1000.     len = msg->mn_Length;
  1001.     if (len == 0)
  1002.         break;
  1003.     --len;                  /*  Fix length up   */
  1004.     Write(fh, msg+1, len);
  1005.     FreeMem(msg,sizeof(MSG)+len+1);
  1006.     }
  1007.     Close(fh);
  1008.     DeletePort(Dbport);
  1009.     PutMsg(Dback,&DummyMsg);          /*  Kill handshake  */
  1010. }
  1011.  
  1012. /*
  1013.  *  The assembly tag for the DOS process:  CNOP causes alignment problems
  1014.  *  with the Aztec assembler for some reason.  I assume then, that the
  1015.  *  alignment is unknown.  Since the BCPL conversion basically zero's the
  1016.  *  lower two bits of the address the actual code may start anywhere around
  1017.  *  the label....  Sigh....  (see CreatProc() above).
  1018.  */
  1019.  
  1020. #asm
  1021.     public    _debugproc
  1022.     public    _debugmain
  1023.  
  1024.     cseg
  1025.     nop
  1026.     nop
  1027.     nop
  1028. _debugproc:
  1029.     nop
  1030.     nop
  1031.     movem.l D2-D7/A2-A6,-(sp)
  1032.     jsr    _debugmain
  1033.     movem.l (sp)+,D2-D7/A2-A6
  1034.     rts
  1035. #endasm
  1036.  
  1037.  
  1038. #endif
  1039.  
  1040.  
  1041.